#ifndef _STRUCTURE_H
#define _STRUCTURE_H

#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <cassert>

#include "util.h"
#include "classifier.h"

using namespace std;


class structure {
   class node {
      public:
   string root,left,right;
   int li,ri;
   double prob, thisProb;

   node() {}

   node(const string &s, int l, int r, double p, double tp, const string &ll, const string &rr) {
      root = s;
      li = l;
      ri = r;
      prob = p;
      thisProb=tp;
      left = ll;
      right = rr;
   }

   bool operator < (const node &o) const {
      return prob > o.prob;
   }

   ostream &write(ostream &out) const ;
   };

   // data
   vector <vector <vector <node> > > n;
   vector <int> st, en; // start and end words for each leaf

   void giveFirstLabels_helper(vector <string> &pr, vector <int> &ps1, vector <int> &pe1, vector <int> &ps2, vector <int> &pe2, int i, int j, int k) const;

   void giveFirstRelEntLabels_helper(vector <string> &pr, vector <int> &ps, vector <int> &pe, int i, int j, int k) const;

   public:

   structure (int i);
   structure (const vector <int> &s, const vector <int> &e);
   structure (const vector <string> &str, const vector <int> &s, const vector <int> &e);

   void putInternalLabel(int i, int j, const string &r, const string &ll, const string &rr);

   void putBottomLabel(int i, const string &r, int s, int e);

   int rlevel() const {
      return n.size()-1;
   }

   void fillIn();

   bool entityMatch(int s, int e, const string &r) const;

   void giveFirstRelEntLabels(vector <string> &pr, vector <int> &ps, vector <int> &pe) const;   

   void giveFirstLabels(vector <string> &pr, vector <int> &ps1, vector <int> &pe1, vector <int> &ps2, vector <int> &pe2) const;

   void giveLeafLabels(vector <int> &s, vector <int> &e, vector <int> &r, int i, int j, int k) const;

   void giveBottomEgs(vector <vector <string> > &pr, vector <int> &ps, vector <int> &pe) const;   
   void giveInternalEgs(vector <vector <string> > &pr, vector <vector <int> > &s, vector <vector <int> > &e, vector <vector <vector <string> > > &path, vector <vector <vector <double> > > &pathProb) const;

   void giveNodeInfo(int i, int j, int k, int s, int e, string &l, double &tp) const;
   void givePathInfo(int i, int j, int k, vector <vector <string> > &path, vector <vector <double> > &pathProb) const;

   void giveProds(vector <vector <string> > &pr) const;

   void parse(vector <classifier> &cl, vector <int> &w, vector <int> &pt);

   ostream &write(ostream &out) const;
};
inline ostream& operator << (ostream& out, const structure &s) {
   return s.write(out);
}

#endif
